home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / termsorc.lha / Extras / Source / term-source.lha / termFastMacroWindow.c < prev    next >
C/C++ Source or Header  |  1995-09-26  |  21KB  |  1,044 lines

  1. /*
  2. **    termFastMacroWindow.c
  3. **
  4. **    Fast! macro window support routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Window border scroller. */
  13.  
  14. enum    {    GAD_SCROLLER = 10000,GAD_UP,GAD_DOWN };
  15.  
  16.     /* The arrow image height. */
  17.  
  18. #define ARROW_HEIGHT    11
  19.  
  20.     /* Pack two words into a long. */
  21.  
  22. #define PACK_ULONG(a,b)    (((ULONG)(a)) << 16 | b)
  23.  
  24.     /* Gadget extension. */
  25.  
  26. struct ButtonInfo
  27. {
  28.     struct Image    *ButtonImage;
  29.     STRPTR         ButtonCommand;
  30.     LONG         NumChars;
  31. };
  32.  
  33.     /* A private button gadget attribute. */
  34.  
  35. #define BGA_Command    (TAG_USER + 1)
  36.  
  37.     /* Private button gadget class. */
  38.  
  39. STATIC struct IClass        *ButtonClass;
  40.  
  41.     /* Window border scroller. */
  42.  
  43. STATIC struct Gadget        *Scroller,
  44.                 *UpArrow,
  45.                 *DownArrow;
  46.  
  47.     /* Width of the window border scroller. */
  48.  
  49. STATIC UWORD             RightBorderWidth;
  50.  
  51.     /* Scroller arrow imagery. */
  52.  
  53. STATIC struct Image        *UpImage,
  54.                 *DownImage;
  55.  
  56.     /* The window zoom box. */
  57.  
  58. STATIC struct IBox         WindowZoomBox = { -1,-1,-1,-1 };
  59.  
  60.     /* The fast macro buttons. */
  61.  
  62. STATIC struct Gadget        *Buttons;
  63.  
  64.     /* The first visible button and the number buttons
  65.      * visible in total.
  66.      */
  67.  
  68. STATIC LONG             ButtonTop,
  69.                  ButtonCount;
  70.  
  71.     /* RenderText():
  72.      *
  73.      *    Render the button text.
  74.      */
  75.  
  76. STATIC VOID __regargs
  77. RenderText(struct RastPort *RPort,struct GadgetInfo *GadgetInfo,struct Gadget *Gadget,LONG Len)
  78. {
  79.     UWORD    Width    = (GadgetInfo -> gi_Window -> Width - (GadgetInfo -> gi_Window -> BorderLeft + GadgetInfo -> gi_Window -> BorderRight + 4));
  80.     STRPTR    Label    = (STRPTR)Gadget -> GadgetText;
  81.     ULONG    State;
  82.     UWORD    Pen;
  83.  
  84.         /* Which state is the button in? */
  85.  
  86.     if(Gadget -> Flags & GFLG_SELECTED)
  87.     {
  88.         State    = IDS_SELECTED;
  89.         Pen    = GadgetInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN];
  90.     }
  91.     else
  92.     {
  93.         State    = IDS_NORMAL;
  94.         Pen    = GadgetInfo -> gi_DrInfo -> dri_Pens[TEXTPEN];
  95.     }
  96.  
  97.         /* Render the frame. */
  98.  
  99.     DoMethod(Gadget -> GadgetRender,IM_DRAWFRAME,RPort,PACK_ULONG(Gadget -> LeftEdge + 2,Gadget -> TopEdge),State,GadgetInfo -> gi_DrInfo,PACK_ULONG(Width,Gadget -> Height));
  100.  
  101.         /* Set the rendering pens. */
  102.  
  103.     if(Kick30)
  104.         SetABPenDrMd(RPort,Pen,0,JAM1);
  105.     else
  106.     {
  107.         SetDrMd(RPort,JAM1);
  108.         SetAPen(RPort,Pen);
  109.     }
  110.  
  111.         /* Render the button label. */
  112.  
  113.     Move(RPort,Gadget -> LeftEdge + 4,Gadget -> TopEdge + (Gadget -> Height - GadgetInfo -> gi_DrInfo -> dri_Font -> tf_YSize) / 2 + GadgetInfo -> gi_DrInfo -> dri_Font -> tf_Baseline);
  114.     Text(RPort,Label,Len);
  115. }
  116.  
  117.     /* SetButton():
  118.      *
  119.      *    Set an aspect of the button.
  120.      */
  121.  
  122. STATIC ULONG __regargs
  123. SetButton(struct IClass *class,Object *object,struct opSet *SetInfo)
  124. {
  125.     struct ButtonInfo    *ButtonInfo = INST_DATA(class,object);
  126.     struct TagItem        *Tag,*TagList = SetInfo -> ops_AttrList;
  127.     struct RastPort        *RPort;
  128.     STRPTR             Label;
  129.     BOOLEAN             Finished = FALSE;
  130.  
  131.         /* Scan the attribute list. */
  132.  
  133.     while(Tag = NextTagItem(&TagList))
  134.     {
  135.         switch(Tag -> ti_Tag)
  136.         {
  137.                 // New command string?
  138.  
  139.             case BGA_Command:
  140.  
  141.                 ButtonInfo -> ButtonCommand = (STRPTR)Tag -> ti_Data;
  142.                 break;
  143.  
  144.                 // New label text?
  145.  
  146.             case GA_Text:
  147.  
  148.                 Label = (STRPTR)Tag -> ti_Data;
  149.  
  150.                 ((struct Gadget *)object) -> GadgetText = (struct IntuiText *)Label;
  151.  
  152.                 if(RPort = ObtainGIRPort(SetInfo -> ops_GInfo))
  153.                 {
  154.                     struct TextExtent Extent;
  155.  
  156.                     ButtonInfo -> NumChars = TextFit(RPort,Label,strlen(Label),&Extent,NULL,1,((struct Gadget *)object) -> Width - 8,32767);
  157.  
  158.                     RenderText(RPort,SetInfo -> ops_GInfo,(struct Gadget *)object,ButtonInfo -> NumChars);
  159.  
  160.                     ReleaseGIRPort(RPort);
  161.                 }
  162.  
  163.                 Finished = TRUE;
  164.  
  165.                 break;
  166.         }
  167.     }
  168.  
  169.     if(Finished)
  170.         return(TRUE);
  171.     else
  172.         return(DoSuperMethodA(class,object,(Msg)SetInfo));
  173. }
  174.  
  175.     /* RenderButton():
  176.      *
  177.      *    Render the button label.
  178.      */
  179.  
  180. STATIC ULONG __regargs
  181. RenderButton(struct IClass *class,Object *object,struct gpRender *RenderInfo)
  182. {
  183.     struct ButtonInfo *ButtonInfo = INST_DATA(class,object);
  184.  
  185.         /* No label length calculated yet? */
  186.  
  187.     if(!ButtonInfo -> NumChars)
  188.     {
  189.         STRPTR            Label = (STRPTR)((struct Gadget *)object) -> GadgetText;
  190.         struct TextExtent    Extent;
  191.  
  192.         ButtonInfo -> NumChars = TextFit(RenderInfo -> gpr_RPort,Label,strlen(Label),&Extent,NULL,1,((struct Gadget *)object) -> Width - 8,32767);
  193.     }
  194.  
  195.     RenderText(RenderInfo -> gpr_RPort,RenderInfo -> gpr_GInfo,(struct Gadget *)object,ButtonInfo -> NumChars);
  196.  
  197.     return(TRUE);
  198. }
  199.  
  200.     /* FreeButton():
  201.      *
  202.      *    Free a button gadget object.
  203.      */
  204.  
  205. STATIC ULONG __regargs
  206. FreeButton(struct IClass *class,Object *object,Msg msg)
  207. {
  208.     struct ButtonInfo *ButtonInfo = INST_DATA(class,object);
  209.  
  210.     if(ButtonInfo -> ButtonImage)
  211.         DisposeObject(ButtonInfo -> ButtonImage);
  212.  
  213.     return(DoSuperMethodA(class,object,msg));
  214. }
  215.  
  216.     /* NewButton():
  217.      *
  218.      *    Create a new button object.
  219.      */
  220.  
  221. STATIC ULONG __regargs
  222. NewButton(struct IClass *class,Object *object,struct opSet *SetMethod)
  223. {
  224.     LONG         Width,
  225.              Height;
  226.     struct TagItem    *Tag;
  227.     struct Gadget    *NewGadget = NULL;
  228.  
  229.         /* Determine object width. */
  230.  
  231.     if(Tag = FindTagItem(GA_Width,SetMethod -> ops_AttrList))
  232.         Width = Tag -> ti_Data;
  233.     else
  234.         Width = 0;
  235.  
  236.         /* Determine object height. */
  237.  
  238.     if(Tag = FindTagItem(GA_Height,SetMethod -> ops_AttrList))
  239.         Height = Tag -> ti_Data;
  240.     else
  241.         Height = 0;
  242.  
  243.         /* Proper dimensions? */
  244.  
  245.     if(Width && Height)
  246.     {
  247.         struct Image *ButtonImage;
  248.  
  249.             /* Create a button frame. */
  250.  
  251.         if(ButtonImage = NewObject(NULL,"frameiclass",
  252.             IA_Width,    Width,
  253.             IA_Height,    Height,
  254.         TAG_DONE))
  255.         {
  256.             struct TagItem    *OldTags = SetMethod -> ops_AttrList,
  257.                      NewTags[2];
  258.  
  259.                 /* Add new tag values. */
  260.  
  261.             NewTags[0] . ti_Tag    = GA_Image;
  262.             NewTags[0] . ti_Data    = (ULONG)ButtonImage;
  263.             NewTags[1] . ti_Tag    = TAG_MORE;
  264.             NewTags[1] . ti_Data    = (ULONG)OldTags;
  265.  
  266.             SetMethod -> ops_AttrList = NewTags;
  267.  
  268.                 /* Create new object. */
  269.  
  270.             if(NewGadget = (struct Gadget *)DoSuperMethodA(class,object,(Msg)SetMethod))
  271.             {
  272.                 struct ButtonInfo *ButtonInfo = INST_DATA(class,NewGadget);
  273.  
  274.                     /* Clear the number of characters displayed,
  275.                      * the first rendering call will adjust it.
  276.                      */
  277.  
  278.                 ButtonInfo -> NumChars = 0;
  279.  
  280.                     /* Install the corresponding command. */
  281.  
  282.                 if(Tag = FindTagItem(BGA_Command,OldTags))
  283.                     ButtonInfo -> ButtonCommand = (STRPTR)Tag -> ti_Data;
  284.  
  285.                     /* Remember the frame image. */
  286.  
  287.                 ButtonInfo -> ButtonImage = ButtonImage;
  288.  
  289.                     /* Restore the tags. */
  290.  
  291.                 SetMethod -> ops_AttrList = OldTags;
  292.             }
  293.             else
  294.             {
  295.                 DisposeObject(ButtonImage);
  296.  
  297.                 CoerceMethod(class,(Object *)NewGadget,OM_DISPOSE);
  298.  
  299.                 return(0);
  300.             }
  301.         }
  302.     }
  303.  
  304.     return((ULONG)NewGadget);
  305. }
  306.  
  307.     /* HandleButton():
  308.      *
  309.      *    Handle button input.
  310.      */
  311.  
  312. STATIC ULONG __regargs
  313. HandleButton(struct IClass *class,Object *object,struct gpInput *InputInfo)
  314. {
  315.     ULONG             Result        = GMR_MEACTIVE;
  316.     BOOLEAN             Redraw        = FALSE,
  317.                  Final        = FALSE;
  318.     struct ButtonInfo    *ButtonInfo    = INST_DATA(class,object);
  319.     struct Gadget        *Button        = (struct Gadget *)object;
  320.  
  321.         /* Only mouse events trigger actions. */
  322.  
  323.     if(InputInfo -> gpi_IEvent -> ie_Class == IECLASS_RAWMOUSE)
  324.     {
  325.             /* Selection cancelled or no command available? */
  326.  
  327.         if(InputInfo -> gpi_IEvent -> ie_Code == MENUDOWN || !ButtonInfo -> ButtonCommand[0])
  328.         {
  329.             if(Button -> Flags & GFLG_SELECTED)
  330.             {
  331.                 Button -> Flags &= ~GFLG_SELECTED;
  332.  
  333.                 Redraw = TRUE;
  334.             }
  335.  
  336.             Result = GMR_NOREUSE;
  337.  
  338.                 /* No further actions, please. */
  339.  
  340.             Final = TRUE;
  341.         }
  342.         else
  343.         {
  344.                 /* Select button released? */
  345.  
  346.             if(InputInfo -> gpi_IEvent -> ie_Code == SELECTUP)
  347.             {
  348.                 if(Button -> Flags & GFLG_SELECTED)
  349.                 {
  350.                     *InputInfo -> gpi_Termination = 0;
  351.  
  352.                     Button -> Flags &= ~GFLG_SELECTED;
  353.  
  354.                     Redraw = TRUE;
  355.                 }
  356.                 else
  357.                     *InputInfo -> gpi_Termination = 1;
  358.  
  359.                 Result = GMR_REUSE | GMR_VERIFY;
  360.  
  361.                     /* No further actions, please. */
  362.  
  363.                 Final = TRUE;
  364.             }
  365.         }
  366.     }
  367.  
  368.         /* Change highlighting mode? */
  369.  
  370.     if(!Final)
  371.     {
  372.             /* Hit inside the boundaries? */
  373.  
  374.         if(DoMethod((Object *)ButtonInfo -> ButtonImage,IM_HITFRAME,PACK_ULONG(InputInfo -> gpi_Mouse . X,InputInfo -> gpi_Mouse . Y),PACK_ULONG(Button -> Width,Button -> Height)))
  375.         {
  376.             if(!(Button -> Flags & GFLG_SELECTED))
  377.             {
  378.                 Button -> Flags |= GFLG_SELECTED;
  379.  
  380.                 Redraw = TRUE;
  381.             }
  382.         }
  383.         else
  384.         {
  385.             if(Button -> Flags & GFLG_SELECTED)
  386.             {
  387.                 Button -> Flags &= ~GFLG_SELECTED;
  388.  
  389.                 Redraw = TRUE;
  390.             }
  391.         }
  392.     }
  393.  
  394.         /* Redraw the object? */
  395.  
  396.     if(Redraw)
  397.     {
  398.         struct RastPort *RPort;
  399.  
  400.         if(RPort = ObtainGIRPort(InputInfo -> gpi_GInfo))
  401.         {
  402.             RenderText(RPort,InputInfo -> gpi_GInfo,Button,ButtonInfo -> NumChars);
  403.  
  404.             ReleaseGIRPort(RPort);
  405.         }
  406.     }
  407.  
  408.     return(Result);
  409. }
  410.  
  411.     /* ButtonDispatch():
  412.      *
  413.      *    The button gadget class dispatcher.
  414.      */
  415.  
  416. STATIC ULONG __saveds __asm
  417. ButtonDispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg)
  418. {
  419.         /* Select the message method. */
  420.  
  421.     switch(msg -> MethodID)
  422.     {
  423.         case OM_NEW:
  424.  
  425.             return(NewButton(class,object,(struct opSet *)msg));
  426.  
  427.         case OM_UPDATE:
  428.         case OM_SET:
  429.  
  430.             return(SetButton(class,object,(struct opSet *)msg));
  431.  
  432.         case OM_DISPOSE:
  433.  
  434.             return(FreeButton(class,object,msg));
  435.  
  436.         case GM_RENDER:
  437.  
  438.             return(RenderButton(class,object,(struct gpRender *)msg));
  439.  
  440.         case GM_HITTEST:
  441.  
  442.             return(GMR_GADGETHIT);
  443.  
  444.         case GM_GOINACTIVE:
  445.  
  446.             return(0);
  447.  
  448.         case GM_GOACTIVE:
  449.  
  450.             return(GMR_MEACTIVE);
  451.  
  452.         case GM_HANDLEINPUT:
  453.  
  454.             return(HandleButton(class,object,(struct gpInput *)msg));
  455.  
  456.         default:
  457.  
  458.             return(DoSuperMethodA(class,object,msg));
  459.     }
  460. }
  461.  
  462.     /* FreeButtonClass(VOID):
  463.      *
  464.      *    Free private button gadget class.
  465.      */
  466.  
  467. STATIC VOID
  468. FreeButtonClass(VOID)
  469. {
  470.     if(ButtonClass)
  471.     {
  472.         FreeClass(ButtonClass);
  473.  
  474.         ButtonClass = NULL;
  475.     }
  476. }
  477.  
  478.     /* NewButtonClass(VOID):
  479.      *
  480.      *    Create private button gadget class.
  481.      */
  482.  
  483. STATIC BYTE
  484. NewButtonClass(VOID)
  485. {
  486.     if(ButtonClass = MakeClass(NULL,GADGETCLASS,NULL,sizeof(struct ButtonInfo),0))
  487.     {
  488.         ButtonClass -> cl_Dispatcher . h_Entry = (HOOKFUNC)ButtonDispatch;
  489.  
  490.         return(TRUE);
  491.     }
  492.     else
  493.         return(FALSE);
  494. }
  495.  
  496.     /* FastDeleteScroller(VOID):
  497.      *
  498.      *    Delete fast! macro window scroller.
  499.      */
  500.  
  501. STATIC VOID
  502. FastDeleteScroller(VOID)
  503. {
  504.     if(Scroller)
  505.     {
  506.         DisposeObject(Scroller);
  507.  
  508.         Scroller = NULL;
  509.     }
  510.  
  511.     if(UpArrow)
  512.     {
  513.         DisposeObject(UpArrow);
  514.  
  515.         UpArrow = NULL;
  516.     }
  517.  
  518.     if(DownArrow)
  519.     {
  520.         DisposeObject(DownArrow);
  521.  
  522.         DownArrow = NULL;
  523.     }
  524.  
  525.     if(UpImage)
  526.     {
  527.         DisposeObject(UpImage);
  528.  
  529.         UpImage = NULL;
  530.     }
  531.  
  532.     if(DownImage)
  533.     {
  534.         DisposeObject(DownImage);
  535.  
  536.         DownImage = NULL;
  537.     }
  538. }
  539.  
  540.     /* FastCreateScroller(struct Screen *Screen):
  541.      *
  542.      *    Create fast! macro window scroller.
  543.      */
  544.  
  545. STATIC BYTE __regargs
  546. FastCreateScroller(struct Screen *Screen)
  547. {
  548.     struct DrawInfo    *DrawInfo;
  549.     BYTE         Result = FALSE;
  550.  
  551.     if(DrawInfo = GetScreenDrawInfo(Screen))
  552.     {
  553.         struct Image    *SizeImage;
  554.         ULONG         SizeWidth,
  555.                  SizeHeight,
  556.                  ArrowHeight;
  557.         UWORD         SizeType;
  558.  
  559.         if(Screen -> Flags & SCREENHIRES)
  560.             SizeType = SYSISIZE_MEDRES;
  561.         else
  562.             SizeType = SYSISIZE_LOWRES;
  563.  
  564.         if(SizeImage = (struct Image *)NewObject(NULL,"sysiclass",
  565.             SYSIA_Size,    SizeType,
  566.             SYSIA_Which,    SIZEIMAGE,
  567.             SYSIA_DrawInfo,    DrawInfo,
  568.         TAG_DONE))
  569.         {
  570.             GetAttr(IA_Width,    SizeImage,&SizeWidth);
  571.             GetAttr(IA_Height,    SizeImage,&SizeHeight);
  572.  
  573.             DisposeObject(SizeImage);
  574.  
  575.             RightBorderWidth = SizeWidth;
  576.  
  577.             if(UpImage = (struct Image *)NewObject(NULL,"sysiclass",
  578.                 SYSIA_Size,    SizeType,
  579.                 SYSIA_Which,    UPIMAGE,
  580.                 SYSIA_DrawInfo,    DrawInfo,
  581.             TAG_DONE))
  582.             {
  583.                 GetAttr(IA_Height,UpImage,&ArrowHeight);
  584.  
  585.                 if(DownImage = (struct Image *)NewObject(NULL,"sysiclass",
  586.                     SYSIA_Size,    SizeType,
  587.                     SYSIA_Which,    DOWNIMAGE,
  588.                     SYSIA_DrawInfo,    DrawInfo,
  589.                 TAG_DONE))
  590.                 {
  591.                     if(Scroller = NewObject(NULL,"propgclass",
  592.                         GA_ID,        GAD_SCROLLER,
  593.  
  594.                         GA_Top,        Screen -> WBorTop + Screen -> Font -> ta_YSize + 2,
  595.                         GA_RelHeight,    -(Screen -> WBorTop + Screen -> Font -> ta_YSize + 2 + SizeHeight + 1 + 2 * ArrowHeight),
  596.                         GA_Width,    SizeWidth - 8,
  597.                         GA_RelRight,    -(SizeWidth - 5),
  598.  
  599.                         GA_Immediate,    TRUE,
  600.                         GA_FollowMouse,    TRUE,
  601.                         GA_RelVerify,    TRUE,
  602.                         GA_RightBorder,    TRUE,
  603.  
  604.                         PGA_Freedom,    FREEVERT,
  605.                         PGA_NewLook,    TRUE,
  606.                         PGA_Borderless,    TRUE,
  607.  
  608.                         PGA_Visible,    1,
  609.                         PGA_Total,    1,
  610.                     TAG_DONE))
  611.                     {
  612.                         STATIC struct TagItem ArrowMappings[] = { GA_ID,GA_ID,TAG_END };
  613.  
  614.                         if(UpArrow = NewObject(NULL,"buttongclass",
  615.                             GA_ID,        GAD_UP,
  616.  
  617.                             GA_Image,    UpImage,
  618.                             GA_RelRight,    -(SizeWidth - 1),
  619.                             GA_RelBottom,    -(SizeHeight - 1 + 2 * ArrowHeight),
  620.                             GA_Height,    ArrowHeight,
  621.                             GA_Width,    SizeWidth,
  622.                             GA_Immediate,    TRUE,
  623.                             GA_RelVerify,    TRUE,
  624.                             GA_Previous,    Scroller,
  625.                             GA_RightBorder,    TRUE,
  626.  
  627.                             ICA_TARGET,    ICTARGET_IDCMP,
  628.                             ICA_MAP,    ArrowMappings,
  629.                         TAG_DONE))
  630.                         {
  631.                             if(DownArrow = NewObject(NULL,"buttongclass",
  632.                                 GA_ID,        GAD_DOWN,
  633.  
  634.                                 GA_Image,    DownImage,
  635.                                 GA_RelRight,    -(SizeWidth - 1),
  636.                                 GA_RelBottom,    -(SizeHeight - 1 + ArrowHeight),
  637.                                 GA_Height,    ArrowHeight,
  638.                                 GA_Width,    SizeWidth,
  639.                                 GA_Immediate,    TRUE,
  640.                                 GA_RelVerify,    TRUE,
  641.                                 GA_Previous,    UpArrow,
  642.                                 GA_RightBorder,    TRUE,
  643.  
  644.                                 ICA_TARGET,    ICTARGET_IDCMP,
  645.                                 ICA_MAP,    ArrowMappings,
  646.                             TAG_DONE))
  647.                                 Result = TRUE;
  648.                         }
  649.                     }
  650.                 }
  651.             }
  652.         }
  653.  
  654.         FreeScreenDrawInfo(Screen,DrawInfo);
  655.     }
  656.  
  657.     return(Result);
  658. }
  659.  
  660.     /* RefreshFastWindow(WORD FastWindowHeight):
  661.      *
  662.      *    Refresh the contents of the fast! macro window.
  663.      */
  664.  
  665. VOID __regargs
  666. RefreshFastWindow(BYTE FullRefresh)
  667. {
  668.     if(FastWindow)
  669.     {
  670.         LONG Count = (FastWindow -> Height - (FastWindow -> BorderTop + FastWindow -> BorderBottom + 1)) / (2 + UserFontHeight + 2 + 1);
  671.  
  672.         if(FullRefresh)
  673.             ButtonCount = 0;
  674.  
  675.         if(Count == ButtonCount && Buttons)
  676.         {
  677.             LONG NewTop;
  678.  
  679.             if(!GetAttr(PGA_Top,Scroller,(ULONG *)&NewTop))
  680.                 NewTop = 0;
  681.  
  682.             if(NewTop != ButtonTop)
  683.             {
  684.                 ButtonTop = NewTop;
  685.  
  686.                 Count = 0;
  687.  
  688.                 if(FastMacroList . lh_Head -> ln_Succ)
  689.                 {
  690.                     struct DrawInfo *DrawInfo;
  691.  
  692.                     if(DrawInfo = GetScreenDrawInfo(FastWindow -> WScreen))
  693.                     {
  694.                         struct MacroNode    *Node    = (struct MacroNode *)GetListNode(ButtonTop,&FastMacroList);
  695.                         struct Gadget        *Button    = Buttons;
  696.  
  697.                         while(Count < ButtonCount && Node -> mn_Succ)
  698.                         {
  699.                             SetGadgetAttrs(Button,FastWindow,NULL,
  700.                                 GA_Text,    Node -> mn_Macro,
  701.                                 BGA_Command,    Node -> mn_Code,
  702.                             TAG_DONE);
  703.  
  704.                             Count++;
  705.  
  706.                             Button = Button -> NextGadget;
  707.  
  708.                             Node = Node -> mn_Succ;
  709.                         }
  710.  
  711.                         FreeScreenDrawInfo(FastWindow -> WScreen,DrawInfo);
  712.                     }
  713.                 }
  714.             }
  715.         }
  716.         else
  717.         {
  718.             LONG Top = FastWindow -> BorderTop + 1;
  719.  
  720.             if(Buttons)
  721.             {
  722.                 struct Gadget    *Next = Buttons,
  723.                         *Button;
  724.  
  725.                 RemoveGList(FastWindow,Buttons,-1);
  726.  
  727.                 while(Button = Next)
  728.                 {
  729.                     Next = Button -> NextGadget;
  730.  
  731.                     DisposeObject(Button);
  732.                 }
  733.  
  734.                 Buttons = NULL;
  735.             }
  736.  
  737.             ButtonCount = Count;
  738.  
  739.             if(ButtonTop >= FastMacroCount)
  740.                 ButtonTop = FastMacroCount - ButtonCount;
  741.             else
  742.             {
  743.                 if(ButtonTop + ButtonCount > FastMacroCount)
  744.                     ButtonTop = FastMacroCount - ButtonCount;
  745.             }
  746.  
  747.             if(ButtonTop < 0)
  748.                 ButtonTop = 0;
  749.  
  750.             Count = 0;
  751.  
  752.             if(FastMacroList . lh_Head -> ln_Succ)
  753.             {
  754.                 struct DrawInfo *DrawInfo;
  755.  
  756.                 if(DrawInfo = GetScreenDrawInfo(FastWindow -> WScreen))
  757.                 {
  758.                     struct MacroNode    *Node        = (struct MacroNode *)GetListNode(ButtonTop,&FastMacroList);
  759.                     LONG             Width        = FastWindow -> Width - (FastWindow -> BorderLeft + FastWindow -> BorderRight);
  760.                     struct Gadget        *Previous    = NULL,
  761.                                 *Button;
  762.  
  763.                     while(Count < ButtonCount && Node -> mn_Succ)
  764.                     {
  765.                         if(Button = NewObject(ButtonClass,NULL,
  766.                             GA_ID,        Count,
  767.  
  768.                             GA_Top,        Top,
  769.                             GA_Left,    FastWindow -> BorderLeft,
  770.  
  771.                             GA_Width,    Width,
  772.                             GA_Height,    (2 + UserFontHeight + 2),
  773.                             GA_RelVerify,    TRUE,
  774.  
  775.                             GA_DrawInfo,    DrawInfo,
  776.                             GA_Text,    Node -> mn_Macro,
  777.                             BGA_Command,    Node -> mn_Code,
  778.  
  779.                             Previous ? GA_Previous : TAG_IGNORE,Previous,
  780.                         TAG_DONE))
  781.                         {
  782.                             Top += 2 + UserFontHeight + 2 + 1;
  783.  
  784.                             Count++;
  785.  
  786.                             Previous = Button;
  787.  
  788.                             if(!Buttons)
  789.                                 Buttons = Button;
  790.  
  791.                             Node = Node -> mn_Succ;
  792.                         }
  793.                     }
  794.  
  795.                     FreeScreenDrawInfo(FastWindow -> WScreen,DrawInfo);
  796.                 }
  797.             }
  798.  
  799.             if(Count)
  800.             {
  801.                 AddGList(FastWindow,Buttons,-1,-1,NULL);
  802.  
  803.                 RefreshGList(Buttons,FastWindow,NULL,-1);
  804.             }
  805.  
  806.             if(Top < FastWindow -> Height - (FastWindow -> BorderBottom + 1))
  807.             {
  808.                 SetAPen(FastWindow -> RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  809.  
  810.                 RectFill(FastWindow -> RPort,FastWindow -> BorderLeft,Top,FastWindow -> Width - (FastWindow -> BorderRight + 1),FastWindow -> Height - (FastWindow -> BorderBottom + 1));
  811.             }
  812.  
  813.             SetGadgetAttrs(Scroller,FastWindow,NULL,
  814.                 PGA_Top,    ButtonTop,
  815.                 PGA_Visible,    ButtonCount,
  816.                 PGA_Total,    FastMacroCount,
  817.             TAG_DONE);
  818.         }
  819.     }
  820. }
  821.  
  822.     /* CloseFastWindow():
  823.      *
  824.      *    Close the fast! macro window and free the associated resources.
  825.      */
  826.  
  827. VOID
  828. CloseFastWindow()
  829. {
  830.     CheckItem(MEN_FAST_MACROS_WINDOW,FALSE);
  831.  
  832.     if(Buttons)
  833.     {
  834.         struct Gadget    *Next = Buttons,
  835.                 *Button;
  836.  
  837.         RemoveGList(FastWindow,Buttons,-1);
  838.  
  839.         while(Button = Next)
  840.         {
  841.             Next = Button -> NextGadget;
  842.  
  843.             DisposeObject(Button);
  844.         }
  845.  
  846.         Buttons = NULL;
  847.     }
  848.  
  849.     if(FastWindow)
  850.     {
  851.         PutWindowInfo(WINDOW_FAST,FastWindow -> LeftEdge,FastWindow -> TopEdge,FastWindow -> Width,FastWindow -> Height);
  852.  
  853.         ClearMenuStrip(FastWindow);
  854.         CloseWindowSafely(FastWindow);
  855.  
  856.         FastWindow = NULL;
  857.     }
  858.  
  859.     FreeButtonClass();
  860. }
  861.  
  862.     /* OpenFastWindow():
  863.      *
  864.      *    Open the fast! macro window.
  865.      */
  866.  
  867. BYTE
  868. OpenFastWindow()
  869. {
  870.     if(FastWindow)
  871.         return(TRUE);
  872.  
  873.     if(NewButtonClass())
  874.     {
  875.         if(FastCreateScroller(Window -> WScreen))
  876.         {
  877.             LONG    Left    = 0,
  878.                 Top    = 0,
  879.                 Width    = Window -> WScreen -> WBorLeft + 2 + SZ_GetLen("####################") + 2 + RightBorderWidth,
  880.                 Height    = 0;
  881.  
  882.             GetWindowInfo(WINDOW_FAST,&Left,&Top,&Width,&Height,NULL,Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1 + 1 + 10 * (2 + UserFontHeight + 2 + 1) + Window -> WScreen -> WBorBottom);
  883.  
  884.             if(WindowZoomBox . Left == -1)
  885.             {
  886.                 WindowZoomBox . Left    = 0;
  887.                 WindowZoomBox . Top    = 0;
  888.                 WindowZoomBox . Width    = Width;
  889.                 WindowZoomBox . Height    = Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1;
  890.             }
  891.  
  892.             if(FastWindow = OpenWindowTags(NULL,
  893.                 WA_Width,        Width,
  894.                 WA_Height,        Height,
  895.  
  896.                 WA_Left,        Left,
  897.                 WA_Top,            Top,
  898.  
  899.                 WA_DragBar,        TRUE,
  900.                 WA_DepthGadget,        TRUE,
  901.                 WA_CloseGadget,        TRUE,
  902.                 WA_RMBTrap,        TRUE,
  903.                 WA_Zoom,        &WindowZoomBox,
  904. //                WA_NoCareRefresh,    TRUE,
  905.                 BackfillTag,        &BackfillHook,
  906.                 WA_MenuHelp,        TRUE,
  907.                 WA_SimpleRefresh,    TRUE,
  908.  
  909.                 WA_SizeGadget,        TRUE,
  910.  
  911.                 WA_MinWidth,        Width,
  912.                 WA_MaxWidth,        Width,
  913.  
  914.                 WA_MinHeight,        Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1 + 2 * (2 + UserFontHeight + 2 + 1) + 1 + Window -> WScreen -> WBorBottom,
  915.                 WA_MaxHeight,        Window -> WScreen -> Height,
  916.  
  917.                 WA_Title,        LocaleString(MSG_FASTMACROS_FAST_MACROS_TXT),
  918.  
  919.                 WA_NewLookMenus,    TRUE,
  920.                 WA_Gadgets,        Scroller,
  921.  
  922.                 WA_CustomScreen,    Window -> WScreen,
  923.  
  924.                 AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
  925.                 CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
  926.             TAG_DONE))
  927.             {
  928.                 ButtonTop    = 0;
  929.                 ButtonCount    = -1;
  930.  
  931.                 FastWindow -> UserPort = Window -> UserPort;
  932.  
  933.                 if(ModifyIDCMP(FastWindow,DEFAULT_IDCMP | IDCMP_IDCMPUPDATE | IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW))
  934.                 {
  935.                     SetMenuStrip(FastWindow,Menu);
  936.  
  937.                     FastWindow -> Flags &= ~WFLG_RMBTRAP;
  938.  
  939.                     RefreshFastWindow(TRUE);
  940.  
  941.                     CheckItem(MEN_FAST_MACROS_WINDOW,TRUE);
  942.  
  943.                     return(TRUE);
  944.                 }
  945.                 else
  946.                 {
  947.                     FastWindow -> UserPort = NULL;
  948.  
  949.                     CloseWindow(FastWindow);
  950.  
  951.                     FastWindow = NULL;
  952.                 }
  953.             }
  954.  
  955.             FastDeleteScroller();
  956.         }
  957.  
  958.         FreeButtonClass();
  959.     }
  960.  
  961.     return(FALSE);
  962. }
  963.  
  964.     /* HandleFastWindowGadget(ULONG IClass,LONG ICode,LONG GadgetID):
  965.      *
  966.      *    Process fast! macro window input.
  967.      */
  968.  
  969. VOID __regargs
  970. HandleFastWindowGadget(ULONG IClass,LONG ICode,LONG GadgetID)
  971. {
  972.     STATIC BYTE Scrolling = FALSE;
  973.  
  974.     switch(IClass)
  975.     {
  976.         case IDCMP_GADGETUP:
  977.  
  978.             if(GadgetID == GAD_SCROLLER)
  979.                 Scrolling = FALSE;
  980.             else
  981.             {
  982.                 if(GadgetID < GAD_SCROLLER && !ICode)
  983.                 {
  984.                     struct MacroNode *Node;
  985.  
  986.                     if(Node = (struct MacroNode *)GetListNode(GadgetID + ButtonTop,&FastMacroList))
  987.                     {
  988.                         if(Node -> mn_Code[0])
  989.                             SerialCommand(Node -> mn_Code);
  990.                     }
  991.                 }
  992.             }
  993.  
  994.             break;
  995.  
  996.         case IDCMP_GADGETDOWN:
  997.  
  998.             if(GadgetID == GAD_SCROLLER)
  999.             {
  1000.                 Scrolling = TRUE;
  1001.  
  1002.                 RefreshFastWindow(FALSE);
  1003.             }
  1004.  
  1005.             break;
  1006.  
  1007.         case IDCMP_MOUSEMOVE:
  1008.  
  1009.             if(Scrolling)
  1010.                 RefreshFastWindow(FALSE);
  1011.  
  1012.             break;
  1013.  
  1014.         case IDCMP_IDCMPUPDATE:
  1015.  
  1016.             switch(GadgetID)
  1017.             {
  1018.                 case GAD_UP:    if(ButtonTop)
  1019.                         {
  1020.                             SetGadgetAttrs(Scroller,FastWindow,NULL,
  1021.                                 PGA_Top,ButtonTop - 1,
  1022.                             TAG_DONE);
  1023.  
  1024.                             RefreshFastWindow(FALSE);
  1025.                         }
  1026.  
  1027.                         break;
  1028.  
  1029.                 case GAD_DOWN:    if(ButtonTop + ButtonCount < FastMacroCount)
  1030.                         {
  1031.                             SetGadgetAttrs(Scroller,FastWindow,NULL,
  1032.                                 PGA_Top,ButtonTop + 1,
  1033.                             TAG_DONE);
  1034.  
  1035.                             RefreshFastWindow(FALSE);
  1036.                         }
  1037.  
  1038.                         break;
  1039.             }
  1040.  
  1041.             break;
  1042.     }
  1043. }
  1044.